MySQL Binlog(五)——MySQL常见binlog event解析(上) 前言 前面讲了binlog event的基础知识,从这篇文章开始我们就具体来解析binlog中常见的event,了解其具体代表的意义。本文会介绍Format_description_event、Rotate_event、Query_log_event、Rows_query_log_event几种event。
Format_description_event是每个binlog文件开头的一个描述信心的event。
字段
字节数
描述
binlog_version
2字节
binlog结构的版本,v1,v2,v4
server_version
50字节
MySQL server的数据库版本
timestamp
4字节
创建该binlog文件的时间,单位为秒
header_length
1字节
指定公共头部的长度,v4版本中这个值一直为19,说明其他所有的event的extra_header部分都是空,extra_header长度为header_length-19
event_post_header_length
variable size,跟各个版本支持的event类型总数一致
每个event类型,占用一个字节,表示该event类型post-header部分的长度
event-body部分 无
字节解析示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 公共头部部分省略 04 00 //binlog_version :v4版本 35 2e 36 2e 33 34 2d 6c 6f 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //mysql server version :16进制转换为ascii之后,值为5.6.34-log 00 00 00 00 //timestamp: 13 //header length :19,说明该版本的event类型公共头部长度都为19,extra_header长度为header_length-19 38 0d 00 08 00 12 00 04 04 04 04 12 00 00 5c 00 04 1a 08 00 00 00 08 08 08 02 00 00 00 0a 0a 0a 19 19 00 //event_post_header_len:各个类型event的post-header部分长度 01 2e ef 23 e2
Rotate_event 当MySQL切换至新的binlog文件的时候,MySQL会在旧的binlog文件中写入一个ROTATE_EVENT,其内容包含新的binlog文件的文件名以及第一个偏移地址。当在数据库中执行FLUSH LOGS
语句或者binlog文件的大小超过max_binlog_size参数设定的值就会切换新的binlog文件。
字段
字节数
描述
next_binlog_po
8字节
下一个binlog文件起始的偏移地址
event-body部分
字段
字节数
描述
next_binlog_filename
variable string
下一个binlog文件的文件名
字节解析示例 1 2 3 4 公共头部部分省略 04 00 00 00 00 00 00 00 //next_binlog_pos:下一个binlog的起始偏移地址,小端存储,16进制转换为10进制之后为4 6d 79 73 71 6c 2d 62 69 6e 2e 30 30 30 30 30 32 //next_binlog_filename:下一个binlog的文件名,16进制转换为ascii之后,值为mysql-bin.000002 b3 db 0b 9a checksum
Query_log_event 记录更新操作的语句。
字段
字节数
描述
thread_id
4字节
小端存储,执行语句的线程ID号
exec_time
4字节
小端存储,语句执行的时间
db_len
1字节
database名的长度
error_code
2字节
错误号
status_vars_len
2字节
小端存储,这部分,在v1和v3版本的event中是没有的,指定状态值的长度
event-body部分
字段
字节数
描述
status_vars
status_vars_len字节
记录状态值,具体的解析见下表
database_name
db_len+1字节
null-terminaled类型的字符串,记录database的名字
query_statement
不定
执行的语句
check_sum
4字节
校验码
status_vars的解析是,一个字节表示状态的类型,在类型之后按照类型不同紧接着不同字节数的状态值,状态的类型一共有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 enum Query_event_status_vars { Q_FLAGS2_CODE= 0, Q_SQL_MODE_CODE, Q_CATALOG_CODE, Q_AUTO_INCREMENT, Q_CHARSET_CODE, Q_TIME_ZONE_CODE, Q_CATALOG_NZ_CODE, Q_LC_TIME_NAMES_CODE, Q_CHARSET_DATABASE_CODE, Q_TABLE_MAP_FOR_UPDATE_CODE, Q_MASTER_DATA_WRITTEN_CODE, Q_INVOKER, Q_UPDATED_DB_NAMES, Q_MICROSECONDS, Q_COMMIT_TS, Q_COMMIT_TS2, Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP };
不同状态对应的状态值的字节数
状态
对用的code
状态值占用的字节数
Q_FLAGS2_CODE
0
4字节
Q_SQL_MODE_CODE
1
8字节
Q_CATALOG_CODE
2
第一个字节表示catalog_len,总共catalog_len+2个字节
Q_AUTO_INCREMENT
3
4字节
Q_CHARSET_CODE
4
6字节
Q_TIME_ZONE_CODE
5
第一个字节表示time_zone_len,总共time_zone_len+1字节
Q_CATALOG_NZ_CODE
6
第一个字节表示catalog_len,总共catalog_len+1个字节
Q_LC_TIME_NAMES_CODE
7
2字节
Q_CHARSET_DATABASE_CODE
8
2字节
Q_TABLE_MAP_FOR_UPDATE_CODE
9
8字节
Q_MASTER_DATA_WRITTEN_CODE
10
4字节
Q_INVOKER
11
包含两部分,一部分是user,一部分是host。user部分,一个字节表示user_len,接着user_len个字节表示user。host部分,一个字节表示host_len,接着host_len个字节表示host。
Q_UPDATED_DB_NAMES
12
Q_MICROSECONDS
13
3字节
Q_COMMIT_TS
14
Q_COMMIT_TS2
15
Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP
16
1字节
字节解析示例 执行语句:
1 2 3 4 5 6 7 8 9 10 11 12 13 insert into test1(`name`) values('beijing'); root@localhost : (none) 06:07:04> show binlog events in 'mysql-bin.000012'; +------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------+ | mysql-bin.000012 | 4 | Format_desc | 330619 | 120 | Server ver: 5.6.34-log, Binlog ver: 4 | | mysql-bin.000012 | 120 | Query | 330619 | 212 | BEGIN | | mysql-bin.000012 | 212 | Intvar | 330619 | 244 | INSERT_ID=28 | | mysql-bin.000012 | 244 | Query | 330619 | 374 | use `gangshen`; insert into test1(`name`) values('beijing') | | mysql-bin.000012 | 374 | Xid | 330619 | 405 | COMMIT /* xid=2961 */ | +------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------+ 5 rows in set (0.00 sec)
使用mysqlbinlog工具解析binlog文件
1 2 3 4 5 6 7 8 9 # at 244 #180105 15:20:29 server id 330619 end_log_pos 244 CRC32 0xf41b5eaa Intvar SET INSERT_ID=28/*!*/; #180105 15:20:29 server id 330619 end_log_pos 374 CRC32 0x98379221 Query thread_id=106404 exec_time=0 error_code=0 use `gangshen`/*!*/; SET TIMESTAMP=1515183629/*!*/; insert into test1(`name`) values('beijing') /*!*/; # at 374
解析二进制文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 公共头部部分省略。。。。 a4 9f 01 00 //thread_id:执行语句的线程号,小端存储,转换为16进制为106404 00 00 00 00 //exec_time:执行语句的时间,小端存储,转化为16进制为0 08 //db_len:database name的长度,转换为10进制为8 00 00 //error_code:错误号,小端存储,转换为10进制为0 2a 00 //status_vars_len:状态值的长度,小端存储,转换为10进制为42,表示后续的42个字节为状态值的内容 //status_vars_len 00 00 00 00 00 01 00 00 20 40 00 00 00 00 06 03 73 74 64 03 02 00 02 00 04 21 00 21 00 53 00 0c 01 67 61 6e 67 73 68 65 6e 00 67 61 6e 67 73 68 65 6e 00 //database_name:数据库名称,null-terminaled string类型 ,转换为字符串为gangshen 696e7365727420696e746f20746573743128606e616d6560292076616c75657328276265696a696e672729 //query_statement:执行的语句,转换为字符串为:insert into test1(`name`) values('beijing') 21 92 37 98//checksum
Rows_query_log_event 在row格式复制模式下,将query以语句形式记录。在5.6.2版本之后,可以通过设置binlog_rows_query_log_events
参数来控制在row格式复制模式下是否需要将query语句记录到binlog文件中。
无
event-body部分
字段
字节数
描述
str_len
1字节
记录语句长度
statement
str_len字节
对应的语句
checksum
4字节
校验码
字节解析示例 执行语句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 root@localhost : gangshen 09:11:56> insert into test1(`name`) values('rows_query'); Query OK, 1 row affected (0.04 sec) root@localhost : gangshen 09:12:06> show binlog events in 'mysql-bin.000014'; +------------------+-----+-------------+-----------+-------------+--------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+-------------+-----------+-------------+--------------------------------------------------+ | mysql-bin.000014 | 4 | Format_desc | 330619 | 120 | Server ver: 5.6.34-log, Binlog ver: 4 | | mysql-bin.000014 | 120 | Query | 330619 | 201 | BEGIN | | mysql-bin.000014 | 201 | Rows_query | 330619 | 271 | # insert into test1(`name`) values('rows_query') | | mysql-bin.000014 | 271 | Table_map | 330619 | 326 | table_id: 98 (gangshen.test1) | | mysql-bin.000014 | 326 | Write_rows | 330619 | 377 | table_id: 98 flags: STMT_END_F | | mysql-bin.000014 | 377 | Xid | 330619 | 408 | COMMIT /* xid=3032 */ | +------------------+-----+-------------+-----------+-------------+--------------------------------------------------+ 6 rows in set (0.00 sec)
使用mysqlbinlog工具解析binlog文件
1 2 3 4 # at 201 #180108 9:12:06 server id 330619 end_log_pos 271 CRC32 0xdc68af8a Rows_query # insert into test1(`name`) values('rows_query') # at 271
解析二进制文件:
1 2 3 4 公共头部部分省略。。。 2e //str_len:执行语句的长度,转换为10进制为46 696e7365727420696e746f20746573743128606e616d6560292076616c7565732827726f77735f71756572792729 //statement:执行的语句,转换为ascii为insert into test1(`name`) values('rows_query') 8a af 68 dc //check_sum
参考链接